#ifndef ALLINALL_OBJECT
#define ALLINALL_OBJECT

#define MESHS_TYPE
#include"include/allinall_datatype.hpp"

#include<glad/glad.h>
#include<vector>
#include<ctype.h>
using namespace std;

/*此处管理的是在GPU中的数据组
由于VBO、VAO在使用方式上所呈现出来的数据结构极为相似
故可以定义一个其共有的基底类型
共有数据结构的特点：
都使用内存中的顺序存储来存储单次声明的多个索引
由此特点可以定义出：
单次声明的声明目标
单次声明的大小
单次声明的数据指针

基础模型定义：
单元名称
单元索引
单元大小
&&顺序存储采用new方式制造存储空间
*/
class basemanager{
protected:
	vector<char*>name;
	vector<GLuint*>id;
	vector<GLsizei>size;
	PFNGLGENBUFFERSPROC Gen;
	PFNGLBINDBUFFERPROC Bind;
	// void (__stdcall*Gen)(GLsizei,GLuint*);
	// void (__stdcall*Bind)(GLenum,GLuint);
public:
	char*call;
	void listbuffers();
	bool findname(const char*obj);
	bool checkID(size_t obj);
	bool checkIndex(size_t obj,GLuint index);
	void add(const char*call,GLsizei n);
	void bind(const char*type,GLuint index);
	void bind(size_t type,GLuint index);
	~basemanager();
};

class bufferobj:public basemanager{
public:
	bufferobj();
	void putdata(void*data,size_t size);
};

//由于vertexarray有多个数据采集点
/*每定义一个数据采集区间需要知道该数据的
*单点类型
*数据单元大小（个数）
*整个跨度的大小
*此数据的偏移量
*/
class mesh;
class arrayobj:public basemanager{
public:
	arrayobj();
	void setline(mesh*info);
};

#include<typeinfo>
#include<map>
extern GLenum whichtype(char);
class mesh{
private:
	void sort();
public:
	mesh();
	~mesh();
	map<size_t,const char*>kofd;//kinds of data
	map<const char*,size_t>dblk;//data belongs kind
	vector<size_t>lofu;//lenth of unit(value)
	vector<size_t>lofv;//lenth of value(byte)
	vector<size_t>lofd;//lenth of data(unit)
	vector<GLenum>tofd;//type of data
	vector<GLboolean>rbil;//normalize yes/no
	size_t stride;
	size_t stride_byte;
	void*offset(int n);
	vector<void*>ptr;
	void*data;
	size_t size;
	template<class T>
	//sphere是数组长度
	void load(const char*datatype,size_t sphere,size_t stride,T*data){
		if(dblk.find(datatype)==dblk.end()){
			kofd[kofd.size()]=datatype;
			dblk[datatype]=dblk.size();
			lofu.push_back(stride);
			lofv.push_back(sizeof(T));
			lofd.push_back(sphere);
			tofd.push_back(whichtype(typeid(T).name()[0]));
			for(int i=0;i<sphere;++i)
				if(data[i]>1||data[i]<-1)
					rbil.push_back(GL_TRUE);
				else if(i==sphere-1)
					rbil.push_back(GL_FALSE);
			ptr.push_back(NULL);
		}
		else{
			this->stride-=lofu[dblk[datatype]];
			lofu[dblk[datatype]]=stride;
			lofv[dblk[datatype]]=sizeof(T);
			lofd[dblk[datatype]]=sphere;
			tofd[dblk[datatype]]=whichtype(typeid(T).name()[0]);
			for(int i=0;i<sphere;++i)
				if(data[i]>1)
					rbil[dblk[datatype]]=GL_TRUE;
				else if(i==sphere-1)
					rbil[dblk[datatype]]=GL_FALSE;
		}
		this->stride+=stride;
		int temp_index=dblk[datatype];
		free(ptr[temp_index]);
		ptr[temp_index]=(void*)malloc(sphere*lofv[temp_index]);
		memcpy((char*)ptr[temp_index],(char*)data,sphere*lofv[temp_index]);	
		sort();
	}
	// void (*chg)(const char*,size_t,size_t,float*)=&load;
};

#endif